package com.zscat.mallplus.oms.controller;

import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zscat.mallplus.annotation.SysLog;
import com.zscat.mallplus.build.entity.BuildAdv;
import com.zscat.mallplus.build.service.IBuildAdvService;
import com.zscat.mallplus.enums.AllEnum;
import com.zscat.mallplus.enums.ConstansValue;
import com.zscat.mallplus.enums.OrderStatus;
import com.zscat.mallplus.fenxiao.entity.FenxiaoRecords;
import com.zscat.mallplus.fenxiao.mapper.FenxiaoRecordsMapper;
import com.zscat.mallplus.oms.entity.*;
import com.zscat.mallplus.oms.mapper.OmsExpressInfoMapper;
import com.zscat.mallplus.oms.mapper.OmsOrderOperateHistoryMapper;
import com.zscat.mallplus.oms.mapper.OmsOrderSettingMapper;
import com.zscat.mallplus.oms.service.IOmsOrderItemService;
import com.zscat.mallplus.oms.service.IOmsOrderService;
import com.zscat.mallplus.oms.vo.OmsMoneyInfoParam;
import com.zscat.mallplus.oms.vo.OmsOrderDeliveryParam;
import com.zscat.mallplus.oms.vo.OmsReceiverInfoParam;
import com.zscat.mallplus.oms.vo.OrderCountDto;
import com.zscat.mallplus.sys.service.impl.RedisUtil;
import com.zscat.mallplus.ums.entity.UmsMember;
import com.zscat.mallplus.ums.service.IUmsMemberService;
import com.zscat.mallplus.util.EasyPoiUtils;
import com.zscat.mallplus.util.JsonUtils;
import com.zscat.mallplus.util.Kuaiduniao;
import com.zscat.mallplus.util.StringUtils;
import com.zscat.mallplus.utils.CommonResult;
import com.zscat.mallplus.utils.ValidatorUtils;
import com.zscat.mallplus.vo.Rediskey;
//import io.micrometer.core.instrument.util.JsonUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>
 * 订单表
 * </p>
 *
 * @author zscat
 * @since 2019-04-19
 */
@Slf4j
@RestController
@Api(tags = "OmsOrderController", description = "订单表管理")
@RequestMapping("/oms/OmsOrder")
public class OmsOrderController {
    @Resource
    private IOmsOrderService IOmsOrderService;
    @Resource
    private IOmsOrderItemService orderItemService;

    @Resource
    private OmsOrderOperateHistoryMapper omsOrderOperateHistoryMapper;

    @Resource
    FenxiaoRecordsMapper fenxiaoRecordsMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Resource
    private IOmsOrderService orderService;
    @Resource
    private OmsExpressInfoMapper omsExpressInfoMapper;
    @Autowired
    private IUmsMemberService memberService;

    // 物流信息缓存间隔暂定3个小时
    private static final Long maxCacheTime = 1000 * 60 * 60 * 3L;

    public String queryExpressInfo(OmsOrder omsOrder) {
        log.info("查询订单物流信息-开始，orderId={}",omsOrder.getId());
        //调用“三方快递公司”查询物流信息
        String result = exec(omsOrder.getDeliverySn());
        if (org.springframework.util.StringUtils.isEmpty(result)){
            log.error("查询订单物流信息,未查询到订单{}物流信息。",omsOrder.getDeliverySn());
            return null;
        }
        com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(result);
        return result;
    }

    public String exec(String deliverySn){

        String result = null;
        //查询订单物流表
        OmsExpressInfo omsExpressInfo = new OmsExpressInfo();
        omsExpressInfo.setExpressNo(deliverySn);//物流单号
        omsExpressInfo = omsExpressInfoMapper.selectOne(new QueryWrapper<>(omsExpressInfo));
        String expressCorpId;
        if (Objects.nonNull(omsExpressInfo)){
            expressCorpId = omsExpressInfo.getExpressCorpId();//物流公司编码
        } else {
            System.out.println("找不到物流公司信息");
            OmsOrder order = orderService.getOne(new QueryWrapper<OmsOrder>().eq("delivery_sn", deliverySn));
            expressCorpId = order.getDeliveryCompany();
        }



        //调用“三方快递公司-快递鸟”即时查询API
//        KdniaoTrackQueryAPI api = new KdniaoTrackQueryAPI();
        Kuaiduniao kuaiduniao = new Kuaiduniao();
        try {
            log.info("调用“三方快递公司-快递鸟”即时查询AP，入参：expressCorpId={}，deliverySn={}",expressCorpId,deliverySn);
//            result = api.getOrderTracesByJson(expressCorpId, deliverySn, appConfiguration);
            result = kuaiduniao.getOrderTracesByJson(expressCorpId,deliverySn);
            log.info("调用“三方快递公司-快递鸟”即时查询AP，返参：result={}",result);

        } catch (Exception e) {
            e.printStackTrace();
            log.error("调用“三方快递公司-快递鸟”即时查询API-异常",e);
            return null;
        }

        return result;
    }



    /**
     * 快递鸟 查看物流
     */
    @ApiOperation("查看物流")
    @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataType = "Long", paramType = "query")
    @GetMapping(value = "logisticbyapi")
    @PreAuthorize("hasAuthority('oms:OmsOrder:read')")
    public Object getWayBillInfo1(@RequestParam(value = "orderId", required = true) Long orderId) throws Exception {
        try {
            Map<String, Object> returnMap = new HashMap<>();
            OmsOrder order = orderService.getById(orderId);
            if (order == null) {
                return new CommonResult().failed("未查询到订单信息");
            }
            if (false){  // TODO 正式改为false
                // 调用快递公司接口，获取物流信息
                String returnStr = exec(order.getDeliverySn());
                if (org.springframework.util.StringUtils.isEmpty(returnStr)) {
                    log.error("查询物流信息失败,returnStr={}，信息来至于三方快递接口",returnStr);
                    return new CommonResult().failed("未查询到物流信息");
                }
                returnMap = JsonUtils.readJsonToMap(returnStr);
                if (returnMap != null) {
                    returnMap.put("queryTime", System.currentTimeMillis());
                }
                return new CommonResult().success(returnMap);
            }
//            UmsMember member = memberService.getNewCurrentMember();
//
//            if (!order.getMemberId().equals(member.getId())) {
//                return new CommonResult().failed("非当前用户订单");
//            }
            String deliverySn = order.getDeliverySn();
            if (org.springframework.util.StringUtils.isEmpty(deliverySn)){
                log.error("未查询到运单号，orderId={},deliverySn={}",orderId,order.getDeliverySn());
                return new CommonResult().failed("未查询到运单号");
            }


            log.info("开始查询运单号为{}的物流信息", deliverySn);

            // 从redis里获取物流信息
            if (redisUtil.hExists(Rediskey.KDWL_INFO_CACHE, deliverySn)) {
                // redis已经有缓存
                Object kdwlInfo = redisUtil.hGet(Rediskey.KDWL_INFO_CACHE, deliverySn);
                if (ValidatorUtils.notEmpty(kdwlInfo)) {
                    returnMap = JsonUtils.readJsonToMap(kdwlInfo.toString());
                    Long cacheBeginTime = (Long) returnMap.get("queryTime");
                    // 计算已经缓存时长
                    if (System.currentTimeMillis() - cacheBeginTime < maxCacheTime) {
                        // 直接取缓存
                        // kdwlInfoToMap.remove("queryTime");
                        log.info("查询运单号为{}的物流信息结束,物流信息：{},信息来至于Redis缓存", deliverySn, kdwlInfo);
                        return new CommonResult().success(returnMap);
                    }
                }
            }

            //调用快递公司接口，获取物流信息
            String returnStr = queryExpressInfo(order);
            if (org.springframework.util.StringUtils.isEmpty(returnStr)) {
                log.error("查询物流信息失败,returnStr={}，信息来至于三方快递接口",returnStr);
                return new CommonResult().failed("未查询到物流信息");
            }

            returnMap = JsonUtils.readJsonToMap(returnStr);
            if (returnMap != null) {
                returnMap.put("queryTime", System.currentTimeMillis());
            }
            redisUtil.hPut(Rediskey.KDWL_INFO_CACHE, deliverySn, JsonUtils.objectToJson(returnMap));
            log.info("查询运单号为={},的物流信息结束,物流信息：{}", deliverySn, returnStr);

            return new CommonResult().success(returnMap);
        } catch (Exception e) {
            log.error("get waybillInfo error. error=" + e.getMessage(), e);
            return new CommonResult().failed("获取物流信息失败，请稍后重试");
        }
    }



    @SysLog(MODULE = "oms", REMARK = "获取需要发票的订单列表")
    @ApiOperation("获取需要发票的订单列表")
    @GetMapping(value = "list/fp")
    @PreAuthorize("hasAuthority('oms:OmsOrder:read')")
    public Object list(OmsOrder entity,
                       @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                       @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize
    ) {
        try {
            return new CommonResult().success(IOmsOrderService.page(new Page<OmsOrder>(pageNum, pageSize), new QueryWrapper<>(entity).ne("tax_type", 0).orderByDesc("tax_apply_time")));
        } catch (Exception e) {
            log.error("根据条件查询所有订单表列表：%s", e.getMessage(), e);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "上传发票")
    @ApiOperation("上传发票")
    @GetMapping(value = "upload/fp/{orderId:.+}")
    @PreAuthorize("hasAuthority('oms:OmsOrder:read')")
    public Object fp(@PathVariable("orderId") @NotNull Long orderId,
                     @RequestParam("taxContent") String taxContent) {
        try {
            OmsOrder order = IOmsOrderService.getById(orderId);
            if (Objects.nonNull(order)) {
                if (StringUtils.isNotBlank(taxContent)) {
                    order.setIsTax(1);
                    order.setTaxContent(taxContent);
                    order.setTaxUploadTime(new Date());
                    if (IOmsOrderService.updateById(order)) {
                        return new CommonResult().success(order);
                    }
                }
            }
        } catch (Exception e) {
            log.error("根据条件查询所有订单表列表：%s", e.getMessage(), e);
        }
        return new CommonResult().failed();
    }

    @GetMapping(value = "exportList")
    @PreAuthorize("hasAuthority('oms:OmsOrder:read')")
    public Object exportList(OmsOrder order) {
        return new CommonResult().success(IOmsOrderService.list(new QueryWrapper<>(order).orderByDesc("create_time")));
    }

    @SysLog(MODULE = "oms", REMARK = "导出订单数据")
    @GetMapping("/exportExcel")
    public void export(HttpServletResponse response, OmsOrder order) {
        List<OmsOrder> orderList = IOmsOrderService.list(new QueryWrapper<>(order).orderByDesc("create_time"));
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        // 导出操作
        EasyPoiUtils.exportExcel(orderList, "订单数据", "订单数据", OmsOrder.class, "导出订单数据" + dateFormat.format(now) + ".xls", response);
    }


    @SysLog(MODULE = "oms", REMARK = "根据条件查询所有订单表列表")
    @ApiOperation("根据条件查询所有订单表列表")
    @GetMapping(value = "/fenxiaolist")
    public Object getFenxiaoOmsOrderByPage(OmsOrder entity,
                                           @RequestParam(value = "pageNum", defaultValue = "1") Integer pageNum,
                                           @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize
    ) {
        try {
            List<FenxiaoRecords> list = fenxiaoRecordsMapper.selectList(new QueryWrapper<FenxiaoRecords>().eq("level", 1));
            if (ValidatorUtils.empty(list)) {
                return new CommonResult().success();
            }
            List<Long> resultList = new ArrayList<>(list.size());
            for (FenxiaoRecords s : list) {
                resultList.add(s.getOrderId());
            }
            return new CommonResult().success(IOmsOrderService.page(new Page<OmsOrder>(pageNum, pageSize), new QueryWrapper<>(entity).in("id", resultList).orderByDesc("create_time")));
        } catch (Exception e) {
            log.error("根据条件查询所有订单表列表：%s", e.getMessage(), e);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "删除订单表")
    @ApiOperation("删除订单表")
    @GetMapping(value = "/delete/{id}")
    @PreAuthorize("hasAuthority('oms:OmsOrder:delete')")
    public Object deleteOmsOrder(@ApiParam("订单表id") @PathVariable Long id) {
        try {
            if (ValidatorUtils.empty(id)) {
                return new CommonResult().paramFailed("订单表id");
            }
            if (IOmsOrderService.removeById(id)) {
                return new CommonResult().success();
            }
        } catch (Exception e) {
            log.error("删除订单表：%s", e.getMessage(), e);
            return new CommonResult().failed();
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "给订单表分配订单表")
    @ApiOperation("查询订单表明细")
    @GetMapping(value = "/{id}")
    public Object getOmsOrderById(@ApiParam("订单表id") @PathVariable Long id) {
        try {
            if (ValidatorUtils.empty(id)) {
                return new CommonResult().paramFailed("订单表id");
            }
            OmsOrder coupon = IOmsOrderService.getById(id);
            if (coupon != null && coupon.getId() > 0) {
                coupon.setOrderItemList(orderItemService.list(new QueryWrapper<OmsOrderItem>().eq("order_id", coupon.getId())));
                coupon.setHistoryList(omsOrderOperateHistoryMapper.selectList(new QueryWrapper<OmsOrderOperateHistory>().eq("order_id", coupon.getId())));
                return new CommonResult().success(coupon);
            }

            return new CommonResult().failed("订单已删除");
        } catch (Exception e) {
            log.error("查询订单表明细：%s", e.getMessage(), e);
            return new CommonResult().failed();
        }

    }

    @ApiOperation(value = "批量删除订单表")
    @RequestMapping(value = "/delete/batch", method = RequestMethod.GET)
    @ResponseBody
    @SysLog(MODULE = "pms", REMARK = "批量删除订单表")
    @PreAuthorize("hasAuthority('oms:OmsOrder:delete')")
    public Object deleteBatch(@RequestParam("ids") List<Long> ids) {
        boolean count = IOmsOrderService.removeByIds(ids);
        if (count) {
            return new CommonResult().success(count);
        } else {
            return new CommonResult().failed();
        }
    }

    @SysLog(MODULE = "oms", REMARK = "批量发货")
    @ApiOperation("批量发货")
    @RequestMapping(value = "/update/delivery", method = RequestMethod.POST)
    @ResponseBody
    public Object delivery(@RequestBody List<OmsOrderDeliveryParam> deliveryParamList) {
        int count = IOmsOrderService.delivery(deliveryParamList);
        if (count > 0) {
            return new CommonResult().success(count);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "发货")
    @ApiOperation("发货")
    @RequestMapping(value = "delivery", method = RequestMethod.POST)
    @ResponseBody
    public Object singleDelivery(@RequestBody OmsOrderDeliveryParam deliveryParamList) {
        int count = IOmsOrderService.singleDelivery(deliveryParamList);
        if (count > 0) {
            return new CommonResult().success(count);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "批量关闭订单")
    @ApiOperation("批量关闭订单")
    @RequestMapping(value = "/update/close", method = RequestMethod.POST)
    @ResponseBody
    public Object close(@RequestParam("ids") List<Long> ids, @RequestParam String note) {
        int count = IOmsOrderService.close(ids, note);
        if (count > 0) {
            return new CommonResult().success(count);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "修改收货人信息")
    @ApiOperation("修改收货人信息")
    @RequestMapping(value = "/update/receiverInfo", method = RequestMethod.POST)
    @ResponseBody
    public Object updateReceiverInfo(@RequestBody OmsReceiverInfoParam receiverInfoParam) {
        int count = IOmsOrderService.updateReceiverInfo(receiverInfoParam);
        if (count > 0) {
            return new CommonResult().success(count);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "修改订单费用信息")
    @ApiOperation("修改订单费用信息")
    @RequestMapping(value = "/update/moneyInfo", method = RequestMethod.POST)
    @ResponseBody
    public Object updateReceiverInfo(@RequestBody OmsMoneyInfoParam moneyInfoParam) {
        int count = IOmsOrderService.updateMoneyInfo(moneyInfoParam);
        if (count > 0) {
            return new CommonResult().success(count);
        }
        return new CommonResult().failed();
    }

    @SysLog(MODULE = "oms", REMARK = "备注订单")
    @ApiOperation("备注订单")
    @RequestMapping(value = "/update/note", method = RequestMethod.POST)
    @ResponseBody
    public Object updateNote(@RequestParam("id") Long id,
                             @RequestParam("note") String note,
                             @RequestParam("status") Integer status) {
        int count = IOmsOrderService.updateNote(id, note, status);
        if (count > 0) {
            return new CommonResult().success(count);
        }
        return new CommonResult().failed();
    }

    @ApiOperation(value = "查询订单列表")
    @GetMapping(value = "list")
    @PreAuthorize("hasAuthority('oms:OmsOrder:read')")
    public Object orderList(OmsOrder order,
                            @RequestParam(value = "pageSize", required = false, defaultValue = "30") Integer pageSize,
                            @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum) throws ParseException {
        SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd");
        SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        QueryWrapper<OmsOrder> query = new QueryWrapper<>(order).orderByDesc("create_time").select(ConstansValue.sampleOrderList);
        if (ValidatorUtils.notEmpty(order.getPaymentTime())) {
            query.between("payment_time", dateFormat2.parse(dateFormat1.format(order.getPaymentTime()) + " 00:00:00"), dateFormat2.parse(dateFormat1.format(order.getPaymentTime()) + " 23:59:59"));
            order.setPaymentTime(null);
        }
        IPage<OmsOrder> page = IOmsOrderService.page(new Page<OmsOrder>(pageNum, pageSize), query);
        for (OmsOrder omsOrder : page.getRecords()) {
            List<OmsOrderItem> itemList = orderItemService.list(new QueryWrapper<OmsOrderItem>().eq("order_id", omsOrder.getId()).eq("type", AllEnum.OrderItemType.GOODS.code()));
            omsOrder.setOrderItemList(itemList);
        }
        return new CommonResult().success(page);
    }

    /**
     * @Valid 根据商品分类统计订单占比
     */
    @GetMapping("/orderCount")
    public Object orderCount() {
        OrderCountDto orderCountDto = IOmsOrderService.getOrderCount();
        return new CommonResult().success(orderCountDto);
    }

    @GetMapping(value = "/data/count")
    public Object getCount(@RequestParam("status") Integer status) {
        return new CommonResult().success(IOmsOrderService.getOrderTimeData(status));
    }

    @GetMapping(value = "/data/chart")
    public Object getChart() {
        return new CommonResult().success(IOmsOrderService.chartCount());
    }


    @GetMapping(value = "/orderPay/list")
    public Object orderPayList(OmsOrder order,
                               @RequestParam(value = "pageSize", required = false, defaultValue = "10") Integer pageSize,
                               @RequestParam(value = "pageNum", required = false, defaultValue = "1") Integer pageNum) {

        List<Integer> ids = Arrays.asList(OrderStatus.TRADE_SUCCESS.getValue(), OrderStatus.PART_REFUND.getValue());
        IPage<OmsOrder> page = IOmsOrderService.page(new Page<OmsOrder>(pageNum, pageSize), new QueryWrapper<OmsOrder>().in("status", ids).isNull("pid").orderByDesc("create_time").select(ConstansValue.sampleOrderList));
        for (OmsOrder omsOrder : page.getRecords()) {
            List<OmsOrder> itemList = IOmsOrderService.list(new QueryWrapper<OmsOrder>().eq("pid", omsOrder.getId()));
            omsOrder.setChildList(itemList);
        }
        return new CommonResult().success(page);
    }
}
